home *** CD-ROM | disk | FTP | other *** search
/ Nothing but Tetris / Nothing but Tetris.iso / amiga / workbench_tris / key_input.c < prev    next >
C/C++ Source or Header  |  1992-11-19  |  6KB  |  191 lines

  1. /*
  2. Copyright (c) 1992, Trevor Smigiel.  All rights reserved.
  3.  
  4. (I hope Commodore doesn't mind that I borrowed their copyright notice.)
  5.  
  6. The source and executable code of this program may only be distributed in free
  7. electronic form, via bulletin board or as part of a fully non-commercial and
  8. freely redistributable diskette.  Both the source and executable code (including
  9. comments) must be included, without modification, in any copy.  This example may
  10. not be published in printed form or distributed with any commercial product.
  11.  
  12. This program is provided "as-is" and is subject to change; no warranties are
  13. made.  All use is at your own risk.  No liability or responsibility is assumed.
  14.  
  15. */
  16.  
  17. #include <exec/types.h>
  18. #include <exec/memory.h>
  19. #include <exec/tasks.h>
  20. #include <devices/inputevent.h>
  21. #include <devices/input.h>
  22. #include <dos/dos.h>
  23. /* */
  24. #include <proto/exec.h>
  25.  
  26. #include "con_input.h"
  27.  
  28. struct InputEvent *__asm __interrupt
  29. KeyWatch(
  30.             register __a0 struct InputEvent *inputEvents,
  31.             register __a1 struct ControlData *handlerData
  32. )
  33. {
  34.     struct InputEvent *ie = inputEvents;
  35.     struct InputEvent *pie = (struct InputEvent *)&ie;
  36.     char           *key = handlerData->cd_Keys;
  37.     ULONG           s = 0,
  38.                     b;
  39.  
  40.     if (key) while (inputEvents) {
  41.         if (inputEvents->ie_Class == IECLASS_RAWKEY) {
  42.             for (b = 1; *key; key++, b <<= 1) {
  43.                 if (inputEvents->ie_Code & IECODE_UP_PREFIX) {
  44.                     if ((inputEvents->ie_Code & ~IECODE_UP_PREFIX) == *key) {
  45.                         pie->ie_NextEvent = inputEvents->ie_NextEvent;
  46.                         inputEvents = pie;
  47.                         handlerData->cd_State &= ~b;
  48.                     }
  49.                 } else {
  50.                     if (inputEvents->ie_Code == *key) {
  51.                         pie->ie_NextEvent = inputEvents->ie_NextEvent;
  52.                         inputEvents = pie;
  53.                         if (!(handlerData->cd_State & b)) {
  54.                             s = 1;
  55.                             handlerData->cd_State |= b;
  56.                         }
  57.                     }
  58.                 }
  59.             }
  60.         }
  61.         pie = inputEvents;
  62.         inputEvents = inputEvents->ie_NextEvent;
  63.     }
  64.     if (s)
  65.         Signal(handlerData->cd_Task, SIGBREAKF_CTRL_F);
  66.     return ie;
  67. }
  68.  
  69. void
  70. KeyTask(void)
  71. {
  72.     struct MsgPort     *ReplyPort;
  73.     struct MsgPort     *timerPort;
  74.     struct MsgPort     *inputPort;
  75.     struct IOStdReq    *inputReqBlk;
  76.     struct Interrupt   *inputHandler;
  77.     struct timerequest *timerReqBlk;
  78.     struct Task        *ThisTask;
  79.     struct ControlData *cd;
  80.     struct ControlMsg  CMsg;
  81.     ULONG signaled, signals, PortSig, tPortSig;
  82.     char *keys;
  83.  
  84.     Wait(SIGBREAKF_CTRL_F); /* Wait for parent to tell us to go */
  85.  
  86.     ThisTask = FindTask(NULL);
  87.     cd = (struct ControlData *) ThisTask->tc_UserData;
  88.     keys = cd->cd_Keys;
  89.  
  90.     ReplyPort = CreateMsgPort();
  91.     if (ReplyPort) {
  92.         inputPort = CreateMsgPort();
  93.         if (inputPort) {
  94.             inputHandler = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
  95.             if (inputHandler) {
  96.                 inputReqBlk = CreateIORequest(inputPort, sizeof(struct IOStdReq));
  97.                 if (inputReqBlk) {
  98.                     if (!OpenDevice("input.device", NULL, (struct IORequest *) inputReqBlk, NULL)) {
  99.                         inputHandler->is_Code   = (void (*)()) KeyWatch;
  100.                         inputHandler->is_Data   = (APTR) cd;        /* Get this info from task */
  101.                         inputHandler->is_Node.ln_Pri    = 100;
  102.                         inputHandler->is_Node.ln_Name   = "RawKeyHandler";
  103.                         inputReqBlk->io_Data    = (APTR) inputHandler;
  104.                         inputReqBlk->io_Command = IND_ADDHANDLER;
  105.                         DoIO((struct IORequest *) inputReqBlk);
  106.  
  107.                         CMsg.cm_Msg.mn_Node.ln_Type = NT_REPLYMSG;
  108.                         CMsg.cm_Msg.mn_ReplyPort = ReplyPort;
  109.                         CMsg.cm_Msg.mn_Length = sizeof(struct ControlMsg);
  110.                         CMsg.cm_CData = cd;
  111.  
  112.                         timerPort = CreateMsgPort();
  113.                         if (timerPort) {
  114.                             timerReqBlk = (struct timerequest *) CreateIORequest(ReplyPort, sizeof(struct timerequest));
  115.                             if (timerReqBlk) {
  116.                                 if (!OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *)timerReqBlk, 0L)) {
  117.  
  118.                                 /*
  119.                                  * There should be no reason for a user to
  120.                                  * send this task signals, so I figure it is
  121.                                  * safe to use the break sigs.
  122.                                  */
  123.                                     tPortSig = (1 << timerPort->mp_SigBit);
  124.                                     PortSig = (1 << ReplyPort->mp_SigBit);
  125.                                     signals = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F | PortSig | tPortSig;
  126.                                     for (;;) {
  127.                                         signaled = Wait(signals);
  128.  
  129.                                         if (signaled & SIGBREAKF_CTRL_D) cd->cd_Keys = NULL;
  130.                                         if (signaled & SIGBREAKF_CTRL_E) cd->cd_Keys = keys;
  131.  
  132.                                         if (signaled & SIGBREAKF_CTRL_F) {    /* Key pressed */
  133.                                             if (!CheckIO((struct IORequest *)timerReqBlk)) {
  134.                                                 AbortIO((struct IORequest *)timerReqBlk);
  135.                                                 WaitIO((struct IORequest *)timerReqBlk);
  136.                                             }
  137.                                         }
  138.  
  139.                                         if (signaled & PortSig)  while (GetMsg(ReplyPort));
  140.                                         if (signaled & tPortSig) while (GetMsg(timerPort));
  141.  
  142.                                         if (signaled & SIGBREAKF_CTRL_C) break;
  143.  
  144.                                         if ((CheckIO((struct IORequest *)timerReqBlk)) && (cd->cd_State)) {
  145.                                             timerReqBlk->tr_node.io_Command = TR_ADDREQUEST;
  146.                                             timerReqBlk->tr_time.tv_secs  = 0;
  147.                                             timerReqBlk->tr_time.tv_micro = 100000;
  148.                                             SendIO((struct IORequest *)timerReqBlk);
  149.                                             Forbid();
  150.                                             if (CMsg.cm_Msg.mn_Node.ln_Type == NT_REPLYMSG) {
  151.                                                 CMsg.cm_State = cd->cd_State;
  152.                                                 PutMsg(cd->cd_MsgPort, (struct Message *)&CMsg);
  153.                                             }
  154.                                             Permit();
  155.                                         }
  156.                                     }
  157.  
  158.                                     while (CMsg.cm_Msg.mn_Node.ln_Type != NT_REPLYMSG) {
  159.                                         while (GetMsg(ReplyPort));
  160.                                     }
  161.                                     if (!CheckIO((struct IORequest *)timerReqBlk)) {
  162.                                         AbortIO((struct IORequest *)timerReqBlk);
  163.                                         WaitIO((struct IORequest *)timerReqBlk);
  164.                                     }
  165.                                     CloseDevice((struct IORequest *) timerReqBlk);
  166.                                 }
  167.                                 DeleteIORequest((struct IORequest *) timerReqBlk);
  168.                             }
  169.                             DeleteMsgPort(timerPort);
  170.                         }
  171.  
  172.                         inputReqBlk->io_Data = (APTR) inputHandler;
  173.                         inputReqBlk->io_Command = IND_REMHANDLER;
  174.                         DoIO((struct IORequest *) inputReqBlk);
  175.  
  176.                         CloseDevice((struct IORequest *) inputReqBlk);
  177.                     }
  178.                     DeleteIORequest((struct IORequest *) inputReqBlk);
  179.                 }
  180.                 FreeMem(inputHandler, sizeof(struct Interrupt));
  181.             }
  182.             DeleteMsgPort(inputPort);
  183.         }
  184.         DeleteMsgPort(ReplyPort);
  185.     }
  186.     Forbid();
  187.     cd->cd_MsgPort = NULL;
  188.     Signal(cd->cd_Parent, SIGBREAKF_CTRL_F);
  189.     Wait(0L);
  190. }
  191.